﻿using drinking.Helpers;
using drinking.Models;

namespace drinking.Managers
{
    public class StoreManager
    {
        /// <summary>
        /// 这个缓存容器 不需要用map, 直接用list, 门店数量少， 直接遍历查找速度快
        /// 系统运行过程中，Store数据修改了，先更新缓存容器，再更新数据库
        /// </summary>
        public static List<Store> CacheStores { get; set; } = new List<Store>();

        private static object o_lock = new object();

        /// <summary>
        /// 根据门店编码和密码找出当前 门店对象 在 缓存列表中的索引， 如果不存在，返回-1
        /// </summary>
        /// <param name="storeCode">门店编码</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public static int GetStoresIndex4Pwd(string storeCode, string password)
        {
            int count = CacheStores.Count;
            if (count > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    // 缓存命中，返回缓存对象在列表中的索引
                    if (storeCode == CacheStores[i].StoreCode && password == CacheStores[i].Password)
                    {
                        return i;
                    }
                }
            }

            // 缓存未命中， 就从数据库里查询
            lock (o_lock)
            {
                var db = new DBContext().Db;
                Store s = db.Queryable<Store>().Where(store => store.StoreCode == storeCode && store.Password == password).First();
                // 如果从数据库中查到了，存入到缓存中，
                if (s != null)
                {
                    // 在存入到缓存之前，要再次遍历一次缓存列表，防止多线程数据同步问题
                    int _count = CacheStores.Count;
                    if (_count > 0)
                    {
                        for (int i = 0; i < _count; i++)
                        {
                            // 缓存命中，返回缓存对象在列表中的索引
                            if (storeCode == CacheStores[i].StoreCode && password == CacheStores[i].Password)
                            {
                                return i;
                            }
                        }
                    }
                    // 如果再次遍历 缓存中仍然没有，就从数据库查询

                    var storeDrinkList = db.Queryable<StoreDrink>().Where(st => st.StoreId == s.StoreId).ToList();
                    foreach (StoreDrink st in s.StoreDrinkList)
                    {
                        st._Drink = db.Queryable<Drink>().InSingle(st.DrinkId);

                    }
                    s.StoreDrinkList = storeDrinkList.GroupBy<StoreDrink, string>(st => st._Drink.Classify);

                    
                    CacheStores.Add(s);
                    return _count;
                }
            }
            return -1;
        }


        public static int GetStoresIndex4Id(int storeId)
        {
            int count = CacheStores.Count;
            if (count > 0)
            {
                // 缓存命中，返回缓存对象在列表中的索引
                for (int i = 0; i < count; i++)
                {
                    if (storeId == CacheStores[i].StoreId)
                    {
                        return i;
                    }
                }
            }
            
            lock (o_lock)
            {
                // 缓存未命中， 就从数据库里查询
                var db = new DBContext().Db;
                Store store = new DBContext().Db.Queryable<Store>().InSingle(storeId);
                if (store != null)
                {

                    int _count = CacheStores.Count;
                    if (_count > 0)
                    {
                        for (int i = 0; i < _count; i++)
                        {
                            // 缓存命中，返回缓存对象在列表中的索引
                            if (storeId == CacheStores[i].StoreId)
                            {
                                return i;
                            }
                        }
                    }

                    // 如果再次遍历 缓存中仍然没有，就从数据库查询

                    var storeDrinkList = db.Queryable<StoreDrink>().Where(st => st.StoreId == store.StoreId).ToList();
                    foreach (StoreDrink st in store.StoreDrinkList)
                    {
                        st._Drink = db.Queryable<Drink>().InSingle(st.DrinkId);

                    }
                    store.StoreDrinkList = storeDrinkList.GroupBy<StoreDrink, string>(st => st._Drink.Classify);

                    foreach (StoreDrink st in store.StoreDrinkList)
                    {
                        st._Drink = db.Queryable<Drink>().InSingle(st.DrinkId);
                    }
                    CacheStores.Add(store);
                    return _count;
                }
            }
            return -1;
        }


        public static Timer StoreStatusTimer { get; private set;} = new Timer((obj) =>
            {
                foreach (var item in CacheStores)
                {
                   // int storeStatus = 0;
                    // 设备超过45秒心跳时间未更新，证明上位机和服务器断线
                    if ((DateTime.Now - item.HeartbeatTime).TotalSeconds > 45)
                    {
                        if (item.StoreStatus != 20)
                        {
                            item.StoreStatus = 20;
                            new DBContext().Db.Updateable<Store>(item).UpdateColumns(i => new { i.StoreStatus }).ExecuteCommand();
                        }
                    }
                    else // 设备心跳正常
                    {
                        if (item.StoreStatus == 20) 
                        {
                            // 状态先改成设备不通[10]
                            item.StoreStatus = 10;
                            new DBContext().Db.Updateable<Store>(item).UpdateColumns(i => new { i.StoreStatus }).ExecuteCommand();
                        }
                    }

                }
            });
    }
}
